#include <qqtmodbusrtumanager.h>

QQtModbusRtuManager::QQtModbusRtuManager ( QObject* parent ) : QModbusRtuSerialMaster ( parent )
{
    open();

    manager = new QQtModbusSessionManager ( this );

    connect ( this, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( errorOccurred ( QModbusDevice::Error ) ) );

    connect ( this, SIGNAL ( stateChanged ( QModbusDevice::State ) ),
              this, SLOT ( stateChanged ( QModbusDevice::State ) ) );

    connect ( this, SIGNAL ( timeoutChanged ( int ) ),
              this, SLOT ( timeoutChanged ( int ) ) );
}

QQtModbusRtuManager::~QQtModbusRtuManager()
{
    close();
}

QQtModbusSessionManager* QQtModbusRtuManager::getModbusSessionManager()
{
    return manager;
}

QQtModbusSession* QQtModbusRtuManager::sendRawRequest ( const QModbusRequest& request, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusRequest() = request;
    session->setModbusServerAddress ( serverAddress );

    QModbusRequest& netRequest = session->modbusRequest();
    QModbusReply* reply = QModbusRtuSerialMaster::sendRawRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusRtuManager::sendReadRequest ( const QModbusDataUnit& read, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusDataUnit() = read;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusDataUnit();
    QModbusReply* reply = QModbusRtuSerialMaster::sendReadRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusRtuManager::sendWriteRequest ( const QModbusDataUnit& write, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusWriteDataUnit() = write;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusWriteDataUnit();
    QModbusReply* reply = QModbusRtuSerialMaster::sendWriteRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusRtuManager::sendReadWriteRequest ( const QModbusDataUnit& read, const QModbusDataUnit& write,
                                                              int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusDataUnit() = read;
    session->modbusWriteDataUnit() = write;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusDataUnit();
    QModbusDataUnit& netRequest2 = session->modbusWriteDataUnit();
    //reply里面怎么体现写的？不用体现对吧？
    QModbusReply* reply = QModbusRtuSerialMaster::sendReadWriteRequest ( netRequest, netRequest2, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

void QQtModbusRtuManager::errorOccurred ( QModbusDevice::Error error )
{
    pline() << error;
}

void QQtModbusRtuManager::stateChanged ( QModbusDevice::State state )
{
    pline() << state;
}

void QQtModbusRtuManager::timeoutChanged ( int newTimeout )
{
    pline() << newTimeout;
}

void QQtModbusRtuManager::localReplyFinished()
{
    QModbusReply* reply = ( QModbusReply* ) sender();
    //pline() << reply;

    //clear resource
    QQtModbusSession* s0 = manager->getSessionByReply ( reply );
    //pline() << reply << s0;

    if ( !s0 )
        return;

    //pline() << s0->getModbusReply() << s0->getTimer();
    emit replyFinished ( s0 );

    s0->getTimer()->stop();
    s0->getModbusReply()->deleteLater();
    manager->removeModbusSession ( s0 );
}

void QQtModbusRtuManager::localReplyTimeOut()
{
    QTimer* timer = ( QTimer* ) sender();
    pline() << timer;

    QQtModbusSession* s0 = manager->getSessionByTimer ( timer );

    if ( !s0 )
        return;

    emit replyTimeOut ( s0 ); //请求失败
    //s0->getModbusReply()->abort();
    s0->getModbusReply()->deleteLater();
    manager->removeModbusSession ( s0 );
}

void QQtModbusRtuManager::localReplyErrorOccurred ( QModbusDevice::Error )
{
    QModbusReply* reply = ( QModbusReply* ) sender();
    //pline() << reply;
    QQtModbusSession* session = manager->getSessionByReply ( reply );
    if ( !session )
        return;
    emit replyErrorOccurred ( session );
    session->getModbusReply()->deleteLater();
    manager->removeModbusSession ( session );
}
